/**
 * 解析select表单项选择数据对象, 主要应用select反显、详情页面文本解析 ,思路如下:
 * 
 * 第一步 value如果是对象,则直接从返回value
 * 第二步 从pro-select cacheOptionMaps 获取
 * 第三步 从elForm中的detailModel数据模型中获取
 * 第四步 从数据源中获取: 字典、上下文、服务接口
 * @author xiufu.wang
 */

import { isObject, isArray, objectProperty } from './util';
import treeArray from './tree-array';

export function isLikeOption(v) {
    return (isObject(v) && 'value' in v && 'label' in v) || (isArray(v) && isObject(v[0]) && 'value' in v[0] && 'label' in v[0])
}

function isEmptyValue(value) {
    if (value == null || value === undefined || (typeof value === 'string' && value.trim() === '')) {
        return true
    }
    let nv = isArray(value) ? value : [value]
    if (nv.length === 0) {
        return true
    }
    return false
}

export default function (vm, value, configProvide, includeSource) {
    // value 
    if (isEmptyValue(value)) {
        return null
    }
    includeSource = includeSource || {};
    // 获取明细数据
    const detailModel = objectProperty(vm, 'elForm.detailModel', null)
    // pro-select 规范
    const dataSource = objectProperty(vm, 'realDataSource', null)
    // prop path
    const prop = objectProperty(vm, 'elFormItem.prop', null)
    // configProvide config
    const config = objectProperty(configProvide, 'config', {})
    // pro-select cacheOptionMaps
    const cacheOptionMaps = objectProperty(vm, 'cacheOptionMaps', null)
    //-----------------------从value获取 start------------------------------------
    if (isLikeOption(value)) {
        return value
    }
    //-----------------------从value获取 end------------------------------------

    //-----------------------从cacheOptionMaps获取 start------------------------------------
    if (includeSource.cacheOptionMaps !== false && cacheOptionMaps) {
        let _nv = isArray(value) ? value : [value]
        const nv = _nv.filter((k) => !(k in cacheOptionMaps))
        if (nv.length === 0) {
            // 返回null 说明pro-select包含缓存数据
            return _nv.reduce((m, k) => {
                m.push({
                    value: k,
                    label: cacheOptionMaps[k].label
                })
                return m
            }, [])
        }
    }
    //-----------------------从cacheOptionMaps获取 end------------------------------------

    //-----------------------从el-form detailModel获取 start------------------------------------
    if (includeSource.detailModel !== false && prop && isObject(detailModel) && typeof config.getLabelPropFromDetailModel === 'function') {
        let labelProp = config.getLabelPropFromDetailModel(prop) || [];
        labelProp = Array.isArray(labelProp) ? labelProp : [labelProp]
        let label = null;
        for (let i = 0; i < labelProp.length; i++) {
            const textProp = labelProp[i];
            if (textProp) {
                label = objectProperty(detailModel, textProp, null)
            }
            if (label) {
                break;
            }
        }
        if (label !== null) {
            return isArray(value) ? value.map((r, index) => ({ value: r, label: label[index] })) : { value, label }
        }
    }
    //-----------------------从el-form detailModel获取 end------------------------------------

    //-----------------------从dataSource中获取 start------------------------------------
    if (
        dataSource &&
        dataSource.isDataSource
    ) {
        let formatDatas
        let nv = isArray(value) ? value : [value]
        // 已经初始化
        if (dataSource.getInited() === true) {
            formatDatas = Promise.resolve(dataSource.formatDatas)
        } else { // 未初始化
            /**
             * 2024-03-08增加的反显规范
             */
            const valueQueryField = objectProperty(dataSource, 'options.valueQueryField', null);
            if (valueQueryField) {
                // clone数据源用于精确加载
                const cloneDataSource = dataSource.clone(dataSource.name + 'valueQueryField');
                if (cloneDataSource.loading) {
                    cloneDataSource.pending = false
                }
                formatDatas = cloneDataSource.shortLoadDatas({ [valueQueryField]: nv.join(',') }).then(() => {
                    return (cloneDataSource.formatDatas || []).map(r => ({
                        ...r,
                        ...('asAllText' in r ? { label: r.asAllText } : {})
                    }))
                })
            } else {
                formatDatas = dataSource.loadDatas().then(() => dataSource.formatDatas)
            }
        }

        return formatDatas.then((fdatas) => {
            let res = {}
            treeArray(fdatas || [], 'children', function (item) {
                res[item.value] = {
                    label: item.label,
                    value: item.value,
                    currentLabel: item.label
                }
                return null
            })
            return nv.reduce((m, k) => {
                m.push({
                    value: k,
                    /**
                     * 优化: 由于在dev环境模式下,可能涉及到数据源值被改动的问题,导致错误，所以这里做了
                     * 容错处理, 如果未发现label,则使用value原始值当作label
                     */
                    label: res[k] ? res[k].label : k
                })
                return m
            }, [])
        })
    }
    //-----------------------从dataSource中获取 end------------------------------------
}